import pandas as pd
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import joblib


def data_describe():
    # 加载Excel文件
    file_path = 'DT_data.xlsx'
    column_name = '商品价格'

    # 读取数据
    df = pd.read_excel(file_path)
    data = df[column_name]

    # 数据总览
    print(data.describe())

    # 绘制直方图查看数据分布
    plt.figure(figsize=(10, 6))
    plt.hist(data.dropna(), bins='auto', color='skyblue', edgecolor='black')  # 删除NaN值以避免绘图错误
    plt.title('Data Distribution')
    plt.xlabel('Value')
    plt.ylabel('Frequency')
    plt.show()

    # 绘制箱型图检查异常值
    plt.figure(figsize=(10, 6))
    plt.boxplot(data.dropna(), vert=False)  # 同样删除NaN值
    plt.title('Box Plot')
    plt.xlabel('Value')
    plt.show()


def split_group(name):
    # Step 1: Load the Excel file
    file_path = 'DT_data.xlsx'
    data = pd.read_excel(file_path)

    # Step 2: Basic statistics for the "颜色数量" column (optional, for your reference)
    color_count_stats = data[name].describe()
    print(color_count_stats)

    # Step 3: Calculating the boundaries for equal frequency intervals
    num_intervals = 4
    interval_size = len(data) // num_intervals

    # Sorting the data by "颜色数量"
    sorted_data = data[name].sort_values()

    # Finding the boundaries
    boundaries = [sorted_data.iloc[interval_size * i] for i in range(1, num_intervals)]

    # Adding the minimum and maximum values to the boundaries list
    boundaries = [sorted_data.min()] + boundaries + [sorted_data.max()]
    print("Boundaries for equal frequency intervals:", boundaries)


def DT_parse():
    # Step 1: Load the data
    file_path_model = './data/train/decision_tree.xlsx'
    data_model = pd.read_excel(file_path_model)

    # Step 2: Applying Label Encoding to non-numeric columns
    label_encoder_hat = LabelEncoder()
    label_encoder_style = LabelEncoder()
    data_model['帽顶款式'] = label_encoder_hat.fit_transform(data_model['帽顶款式'])
    data_model['风格分类'] = label_encoder_style.fit_transform(data_model['风格分类'])

    # Step 3: Preparing the data for model training
    X = data_model.drop('销售总量标签', axis=1)  # Features
    y = data_model['销售总量标签']  # Target variable

    # Step 4: Splitting the data into training and testing sets
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05)

    # Step 5: Training the Decision Tree Model
    dtree = DecisionTreeClassifier()
    dtree.fit(X_train, y_train)

    # Step 6: Predicting the test set results
    y_pred = dtree.predict(X_test)

    # Step 7: Evaluating the model
    accuracy = accuracy_score(y_test, y_pred)

    # Step 8: Adding the training/testing labels and predictions to the data
    data_model['DataSet'] = 'Training'
    data_model.loc[X_test.index, 'DataSet'] = 'Testing'
    data_model['Predicted 销售总量标签'] = pd.NA
    data_model.loc[X_test.index, 'Predicted 销售总量标签'] = y_pred

    # Step 9: Save the updated dataframe and the model
    output_file_path = './data/predict/DT_data_with_predictions.xlsx'
    data_model.to_excel(output_file_path, index=False)

    model_file_path = './data/decision_tree_model.joblib'
    joblib.dump(dtree, model_file_path)

    # Print the model accuracy
    print("Model Accuracy:", accuracy)


def DT_tree_plot():
    # 加载模型
    model_path = './data/decision_tree_model.joblib'
    loaded_model = joblib.load(model_path)

    feature_names = ['service', 'colors', 'season', 'type', 'style']
    class_name = ['super low', 'low', 'normal', 'high', 'super high']
    # 绘制决策树
    plt.figure(figsize=(20, 10))  # 调整大小以适应您的屏幕
    plot_tree(loaded_model, filled=True, feature_names=feature_names, class_names=class_name, rounded=True, max_depth=3, fontsize=10)
    plt.title("Decision Tree Visualization")
    plt.savefig('decision_tree.png')
    plt.close()
    plt.show()



def indicator_score():

    # 步骤1: 加载需要进行预测的数据集
    file_path_for_prediction = '1.xlsx'
    data_to_predict = pd.read_excel(file_path_for_prediction)

    # 假设实际标签列名为“Actual Label”，请根据实际情况进行修改
    actual_labels = data_to_predict['销售总量标签']
    features = data_to_predict.drop('销售总量标签', axis=1)

    # 步骤2: 加载之前训练的模型
    model_path = './data/decision_tree_model.joblib'
    loaded_model = joblib.load(model_path)

    # 步骤3: 使用模型进行预测
    predictions = loaded_model.predict(features)

    # 步骤4: 计算和打印各项指标
    accuracy = accuracy_score(actual_labels, predictions)
    conf_matrix = confusion_matrix(actual_labels, predictions)
    class_report = classification_report(actual_labels, predictions)

    print("Accuracy:", accuracy)
    print("Confusion Matrix:\n", conf_matrix)
    print("Classification Report:\n", class_report)

    # 获取特征重要性
    feature_importances = pd.DataFrame(loaded_model.feature_importances_,
                                       index=features.columns,
                                       columns=['importance']).sort_values('importance', ascending=False)

    print("Feature Importances:\n", feature_importances)
    # 步骤5: 将预测结果插入到原始数据集中
    data_to_predict['Predicted Label'] = predictions

    # 步骤6: 保存包含预测结果的数据集
    output_file_path = '2.xlsx'
    data_to_predict.to_excel(output_file_path, index=False)

    print("The predictions and metrics have been added to the Excel file and saved.")


if __name__ == '__main__':
    # DT_parse()
    # split_group('销售总量')
    # DT_tree_plot()
    indicator_score()
